//
//  LcToast.m
//  18Birdies
//
//  Created by Lc on 15/4/10.
//  Copyright (c) 2015年 Lc. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "LcFont.h"
#import "LcLog.h"
#import "LcPreconditions.h"
#import "LcToast.h"
#import "LcUIUtility.h"
#import "UIColor+Lc.h"
#import "UILabel+Lc.h"
#import "NSOperationQueue+Lc.h"
#import "UIDevice+Lc.h"
#import "NSString+Lc.h"
#import "UIViewController+Lc.h"

@implementation LcToast

const CGFloat toastHeight = 44.0;
static NSMutableSet<ToastView *> *existingToasts;

+ (void)showToastWithMessage:(NSString*)message {
  [self showToastWithMessage:message durationType:TOAST_DURATION_SHORT];
}

+ (void)showToastWithMessage:(NSString*)message onWindow:(BOOL)onWindow {
  [self showToastWithMessage:message durationType:TOAST_DURATION_SHORT onWindow:onWindow];
}

+ (void)showToastWithMessage:(NSString*)message durationType:(ToastDurationType)durationType {
  LC_CHECK_NOT_EMPTY(message);
  if ([NSThread isMainThread]) {
    [self doShowToastWithMessage:message durationType:durationType];
  } else {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
      [self doShowToastWithMessage:message durationType:durationType];
    }];
  }
}

+ (void)doShowToastWithMessage:(NSString*)message durationType:(ToastDurationType)durationType {
  [self showToastWithMessage:message durationType:durationType onWindow:NO];
}

+ (void)showToastWithMessage:(NSString*)message durationType:(ToastDurationType)durationType onWindow:(BOOL)onWindow {
  LC_CHECK_NOT_EMPTY(message);
  LC_CHECK_IS_MAIN_THREAD();
  if (![AppDelegate sharedInstance].isForeground) {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
      [self doShowToastWithMessage:message durationType:durationType];
    }
                                                  delay:0.25];
    return;
  }

  ToastView *toastView;
  UIViewController *currentViewController = [UIViewController currentViewController];
  if (existingToasts == nil) {
    existingToasts = [[NSMutableSet alloc] init];
  }
  for (ToastView *view in existingToasts) {
    if (view.viewController == currentViewController || view.superview == UIApplication.sharedApplication.keyWindow) {
      toastView = view;
      [toastView updateMessage:message];
      [self cancelPreviousPerformRequestsWithTarget:self selector:@selector(dismissToastWithView:) object:toastView];
    }
  }
  if (toastView == nil) {
    toastView = [ToastView toastViewWithMessage:message inViewController:currentViewController];
  }
  if (durationType == TOAST_DURATION_FOREVER) {
    toastView.backgroundColor = [LC_COLOR_RED colorWithAlphaComponent:0.9];
  }
  if (currentViewController.presentingViewController != nil || onWindow) {
    [UIApplication.sharedApplication.keyWindow addSubview:toastView];
  } else {
    [currentViewController.view addSubview:toastView];
  }
  [existingToasts addObject:toastView];

  CGRect endFrame = CGRectMake(0, [LcUIUtility topGuideY], [LcUIUtility screenWidth], toastHeight);
  if (!CGRectEqualToRect(toastView.frame, endFrame)) {
    [UIView animateWithDuration:0.25
        animations:^{
          toastView.frame = endFrame;
        }
        completion:^(BOOL finished) {
          [self.class performSelector:@selector(dismissToastWithView:)
                           withObject:toastView
                           afterDelay:[self timeIntervalForDurationType:toastView.durationType]];
        }];
  } else {
    [self.class performSelector:@selector(dismissToastWithView:)
                     withObject:toastView
                     afterDelay:[self timeIntervalForDurationType:toastView.durationType]];
  }
}

+ (void)dismissToastWithView:(ToastView*)toastView {
  [UIView animateWithDuration:0.25
                   animations:^{
                     CGRect frame = toastView.frame;
                     frame.size.height = 0;
                     toastView.frame = frame;
                   }
                   completion:^(BOOL finished) {
                     [existingToasts removeObject:toastView];
                     [toastView removeFromSuperview];
                   }];
}

+ (NSTimeInterval)timeIntervalForDurationType:(ToastDurationType)durationType {
  switch (durationType) {
    case TOAST_DURATION_SHORT:
      return 3;
    case TOAST_DURATION_LONG:
      return 5;
    case TOAST_DURATION_FOREVER:
      return 24.0 * 60.0 * 60.0;
    default:
      LC_FAIL();
      return 0;
  }
}

@end

@implementation ToastView : UIView

+ (ToastView *)toastViewWithMessage:(NSString*)message inViewController:(UIViewController *)viewController {
  ToastView* toastWindow =
  [[ToastView alloc] initWithFrame:CGRectMake(0, [LcUIUtility topGuideY], [LcUIUtility screenWidth], 0)];
  const CGFloat labelHorizontalMargin = 30;
  toastWindow.label = [[UILabel alloc]
                       initWithFrame:CGRectMake(labelHorizontalMargin, -toastHeight,
                                                toastWindow.bounds.size.width - 2 * labelHorizontalMargin, toastHeight)];
  toastWindow.label.backgroundColor = [UIColor clearColor];
  [toastWindow.label setLcFont:[LcFont wr14]];
  toastWindow.label.textAlignment = NSTextAlignmentCenter;
  toastWindow.label.numberOfLines = 2;
  toastWindow.label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
  [toastWindow addSubview:toastWindow.label];

  toastWindow.backgroundColor = LC_COLOR_BACKGROUND_BLUE_GRAY_1;
  toastWindow.clipsToBounds = YES;

  [toastWindow updateMessage: message];
  toastWindow.viewController = viewController;
  return toastWindow;
}

- (void)updateMessage:(NSString *)message {
  self.label.text = message;
  CGFloat labelHeight = [message heightOfFont:self.label.font andWidth:self.label.frame.size.width];
  self.durationType = labelHeight > 30.0 ? TOAST_DURATION_LONG : TOAST_DURATION_SHORT;
}

@end
